package com.it.lmao.concurrent;

import java.util.concurrent.Semaphore;

public class UsualSemaphoreSample {
    //Java 提供了经典信号量（Semaphore)）的实现，它通过控制一定数量的允许（permit）的方式，来达到限制通用资源访问的目的。你可以想象一下这个场景，在车站、机场等出租车时，当很多空出租车就位时，
    // 为防止过度拥挤，调度员指挥排队等待坐车的队伍一次进来 5 个人上车，等这 5 个人坐车出发，再放进去下一批，这和 Semaphore 的工作原理有些类似。
    public static void main(String[] args) {
        System.out.println("Action...GO!");
        Semaphore semaphore = new Semaphore(5);
        for (int i = 0; i <10; i++) {
            Thread t = new Thread(new SemaphoreWorker(semaphore));
            t.start();
        }
    }
}
//这段代码是比较典型的 Semaphore 示例，其逻辑是，线程试图获得工作允许，得到许可则进行任务，然后释放许可，这时等待许可的其他线程，就可获得许可进入工作状态，直到全部处理结束。编译运行，
// 我们就能看到 Semaphore 的允许机制对工作线程的限制。
class SemaphoreWorker  implements  Runnable{

    private String name;
    private Semaphore semaphore;
    public SemaphoreWorker(Semaphore semaphore) {
        this.semaphore = semaphore;
    }
    @Override
    public void run() {
        try {
            log("is waiting for a permit!");
            //获取锁
            // 请求独占锁，忽略所有中断，至少执行一次tryAcquire，如果成功就返回，否则线程进入阻塞--唤醒两种状态切换中，直到tryAcquire成功。
            semaphore.acquire();
            log("acquired a permit!");
            log("executed!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            log("released a permit!");
            //释放独占锁，如果tryRelease成功返回true的话就会解开阻塞等待的线程
            //显然，tryRelease方法来释放锁，如果释放成功，先判断head节点是否有效，最后unparkSuccessor启动后续等待的线程。
            semaphore.release();
        }
    }
    private void log(String msg){
        if (name == null) {
            name = Thread.currentThread().getName();
        }
        System.out.println(name + " " + msg);
    }
}
